public class Largest {
public static class TreeNode{
    public int val;
    public TreeNode left;
    public TreeNode right;
}
public static int largestBSTSubtree(TreeNode root){
    return f(root).maxBstSize;//想要的答案
    //主函数只关心一个内容，但是其他信息不可忽略。为了支持可能性计算，还是要返回
    //只是主函数不返回
    //下面的Info函数返回的是4个值
}

public static class Info{
    public long max;//这两个最值使用long是为了保证空树的合理性
    public long min;
    public boolean isBst;
    public int maxBstSize;

    public Info(long a,long b,boolean c,int d){
        max=a;
        min=b;
        isBst=c;
        maxBstSize=d;//想要的答案就一个
    }
}


public static Info f(TreeNode x){
    if(x==null){
        return new Info(Long.MIN_VALUE,Long.MAX_VALUE,true,0);
    }
//x不是空树的时候。  在以下取得左右树的全集 整合出x的信息
    Info infol=f(x.left);//左子树调用f函数，得到左树上的四个信息
    Info infor=f(x.right);//右子树调用f函数，得到右树上的四个信息
   //得到x整棵树最大/小值：左树的最大/小值和右树的最大/小值对比得出整棵树最大/小
    long max =Math.max(x.val,Math.max(infol.max,infor.max));
    long min =Math.min(x.val,Math.min(infol.min,infor.min));
//x整体是不是bst
    boolean isBst=infol.isBst&&infor.isBst&&infol.max<x.val&&x.val<infor.min;

//整棵树是不是bst-->是的话就是第二种情况（包含x）：所有结点
    int maxBSTSize;
    if (isBst){
        maxBSTSize=infol.maxBstSize+infor.maxBstSize+1;//整大颗树的所有结点
    }else {
        //第一种情况（包含x） 左右相比取最大
        maxBSTSize=Math.max(infol.maxBstSize,infor.maxBstSize);
    }
    return new Info(max,min,isBst,maxBSTSize);
}


}
